//替換MESDefaultMapAction.cs  裡的
public void Receive_S1F3W(SecsMessage msg, UInt32 SystemByte)
  {
      UInt32 currentVID = 0; // Used to log VID in case of an error during SetValue
      object currentValue = null; // Used to log the original value in case of an error
      string currentVidName = "UNKNOWN"; // Used to log VID name
      SecsItem.SecsIndexType currentSecsType = default(SecsItem.SecsIndexType); // Used to log SECS type

      try
      {
          SCUtility.jsecsActionRecordMsg(jSecs, true, msg, SystemByte);

          Int32 SVID_Count = new Int32();
          // Get_List returns the count, ensure it's not an error code itself
          if (msg.Body().Get_List(ref SVID_Count) < 0 || SVID_Count < 0)
          {
              logger_SystemError.Error($"[Receive_S1F3W] Invalid SVID_Count ({SVID_Count}) from S1F3 message. SystemByte: {SystemByte}");
              jSecs.UnrecognizedError(UnrecognizedErrorType.InvalidData, ref SystemByte);
              return;
          }

          SecsMessage S1F4 = BodyCreator.Create_S1F4();
          S1F4.Body().Set_List(SVID_Count);

          Dictionary<int, VID> vidDefinitions = null;
          try
          {
              vidDefinitions = jSecs.Read_VID();
              if (vidDefinitions == null)
              {
                  throw new InvalidOperationException("jSecs.Read_VID() returned null.");
              }
          }
          catch (Exception exReadVid)
          {
              logger_SystemError.Error(exReadVid, $"[Receive_S1F3W] Failed to read VID definitions (jSecs.Read_VID()). SystemByte: {SystemByte}. Exception: {exReadVid.Message}");
              //jSecs.UnrecognizedError(UnrecognizedErrorType.SystemError, ref SystemByte);
              jSecs.UnrecognizedError(UnrecognizedErrorType.InvalidData, ref SystemByte);

              return;
          }

          for (int i = 0; i < SVID_Count; i++)
          {
              UInt32[] Request_VID_Array = new UInt32[1]; // SECS U4 is an array of 1 item
              if (msg.Body().I((uint)i).Get_U4(ref Request_VID_Array) == -1)
              {
                  logger_SystemError.Error($"[Receive_S1F3W] Failed to get U4 VID at S1F3 body index {i}. SystemByte: {SystemByte}");
                  jSecs.UnrecognizedError(UnrecognizedErrorType.InvalidData, ref SystemByte);
                  return;
              }
              currentVID = Request_VID_Array[0];
              currentVidName = vidDefinitions.ContainsKey((int)currentVID) ? vidDefinitions[(int)currentVID].Name : "UNKNOWN_VID_NAME";

              logger.Debug($"[Receive_S1F3W] Processing S1F3 item {(i + 1)}/{SVID_Count} - VID: {currentVID} ({currentVidName})");

              Dictionary<SecsItem.SecsIndexType, object> VID_Val_Dict = new Dictionary<SecsItem.SecsIndexType, object>();

              int queryStatus = -1;
              try
              {
                  // Assuming QueryCurrentVID is defined elsewhere in this class or a base class
                  queryStatus = QueryCurrentVID((int)currentVID, ref VID_Val_Dict);
              }
              catch (Exception exQuery)
              {
                  logger_SystemError.Error(exQuery, $"[Receive_S1F3W] Exception during QueryCurrentVID for VID: {currentVID} ({currentVidName}). SystemByte: {SystemByte}. Exception: {exQuery.Message}");
                  //jSecs.UnrecognizedError(UnrecognizedErrorType.SystemError, ref SystemByte);
                  jSecs.UnrecognizedError(UnrecognizedErrorType.InvalidData, ref SystemByte);
                  return;
              }

              if (queryStatus != 0)
              {
                  logger.Warn($"[Receive_S1F3W] QueryCurrentVID failed (returned {queryStatus}) for VID: {currentVID} ({currentVidName}). SystemByte: {SystemByte}");
                  jSecs.UnrecognizedError(UnrecognizedErrorType.InvalidData, ref SystemByte);
                  return;
              }

              if (VID_Val_Dict.Count > 0)
              {
                  foreach (var vobj in VID_Val_Dict)
                  {
                      currentValue = vobj.Value;
                      currentSecsType = vobj.Key;
                      try
                      {
                          logger.Debug($"[Receive_S1F3W] VID: {currentVID} ({currentVidName}), QueryResult Value: '{TruncateValueForLog(currentValue)}' (Type: {currentValue?.GetType().FullName}), TargetSECSDataType: {currentSecsType}");

                          if (currentSecsType == SecsItem.SecsIndexType.List)
                          {
                              if (currentValue is System.Collections.IList listData)
                              {
                                  int listSize = listData.Count;
                                  S1F4.Body().I((uint)i).Set_List(listSize);
                                  for (int listItemIndex = 0; listItemIndex < listSize; listItemIndex++)
                                  {
                                      object listItem = listData[listItemIndex];
                                      SecsItem.SecsIndexType listItemSecsType = DetermineListItemSecsType(currentVID, listItem, listItemIndex);

                                      if (listItemSecsType == default(SecsItem.SecsIndexType))
                                      {
                                          logger_SystemError.Error($"[Receive_S1F3W] VID: {currentVID} ({currentVidName}), List item at index {listItemIndex} has undetermined SECS type. Value: '{TruncateValueForLog(listItem)}' (Type: {listItem?.GetType().FullName}).");
                                          throw new InvalidOperationException($"Could not determine SECS type for list item of VID {currentVID} at index {listItemIndex}.");
                                      }
                                      S1F4.Body().I((uint)i).I((uint)listItemIndex).SetValue(listItemSecsType, listItem);
                                  }
                              }
                              else
                              {
                                  logger_SystemError.Error($"[Receive_S1F3W] VID: {currentVID} ({currentVidName}), queried value for List type is not an IList. Actual type: {currentValue?.GetType().FullName}. Value: '{TruncateValueForLog(currentValue)}'");
                                  // Potentially set an empty list or error for this item in S1F4
                                  S1F4.Body().I((uint)i).Set_List(0); // Example: send <L 0>
                              }
                          }
                          else
                          {
                              S1F4.Body().I((uint)i).SetValue(currentSecsType, currentValue);
                          }
                      }
                      catch (ArgumentException exSetValue)
                      {
                          logger_SystemError.Error(exSetValue, $"[Receive_S1F3W] SetValue ArgumentException for VID: {currentVID} ({currentVidName}). OriginalValue: '{TruncateValueForLog(currentValue)}', OriginalValueType: {currentValue?.GetType().FullName}, TargetSECSDataType: {currentSecsType}. Exception: {exSetValue.Message}");
                          // Handle error for this specific item - e.g., skip or try to set an error if S1F4 allows
                          // If you skip, S1F4 might be malformed if SVID_Count doesn't match actual items.
                          // Consider if the entire S1F4 should be aborted.
                      }
                      catch (NotSupportedException exNotSupported)
                      {
                          logger_SystemError.Error(exNotSupported, $"[Receive_S1F3W] SetValue NotSupportedException for VID: {currentVID} ({currentVidName}). OriginalValue: '{TruncateValueForLog(currentValue)}', OriginalValueType: {currentValue?.GetType().FullName}, TargetSECSDataType: {currentSecsType}. Exception: {exNotSupported.Message}");
                      }
                      catch (Exception exGenericSetValue) // Other exceptions during SetValue or list processing
                      {
                          logger_SystemError.Error(exGenericSetValue, $"[Receive_S1F3W] SetValue Generic Exception for VID: {currentVID} ({currentVidName}). OriginalValue: '{TruncateValueForLog(currentValue)}', OriginalValueType: {currentValue?.GetType().FullName}, TargetSECSDataType: {currentSecsType}. Exception: {exGenericSetValue.Message}");
                      }
                  }
              }
              else
              {
                  logger.Warn($"[Receive_S1F3W] QueryCurrentVID for VID: {currentVID} ({currentVidName}) returned no data (empty dictionary). SystemByte: {SystemByte}");
                  // Handle in S1F4: e.g. S1F4.Body().I((uint)i).Set_List(0); if it's supposed to be a list but is empty,
                  // or set to a default/error value if a single item was expected.
                  // This depends heavily on your SECS spec for the specific VID.
              }
          }

          if (jSecs.Reply(S1F4, SystemByte) != SendReturnCode.Normal)
          {
              // Assuming scApp and SCAppConstants are available
              // scApp.AlarmBLL.onMainAlarm(SCAppConstants.MainAlarmCode.EAP_REPLY_MSG_ERROR_1, "S1F4", SystemByte.ToString());
              logger_SystemError.Error($"[Receive_S1F3W] Failed to send S1F4 reply. SystemByte: {SystemByte}");
          }
          SCUtility.jsecsActionRecordMsg(jSecs, false, S1F4, SystemByte);
      }
      catch (Exception ex)
      {
          logger_SystemError.Error(ex, $"[Receive_S1F3W] Unhandled Exception. SystemByte: {SystemByte}. Last attempted VID: {currentVID} ({currentVidName}). Last Value: '{TruncateValueForLog(currentValue)}'. TargetSECSDataType: {currentSecsType}. Exception: {ex.ToString()}");
          // Consider sending a generic error reply to host if appropriate (e.g., SxF0)
          // jSecs.UnrecognizedError(UnrecognizedErrorType.SystemError, ref SystemByte); // Example
      }
  }
  // THIS IS A PLACEHOLDER AND MUST BE IMPLEMENTED BASED ON YOUR EQUIPMENT'S SECS SPECIFICATION.
  private SecsItem.SecsIndexType DetermineListItemSecsType(UInt32 parentVid, object listItem, int itemIndex)
  {
      // --- Your specific logic here ---
      // This function needs to know, based on 'parentVid' (and potentially 'itemIndex' if the list has a fixed structure),
      // what the SECS data type of 'listItem' should be.

      // Example:
      // if (parentVid == 12345) // VID 12345 is a List of U2 values
      // {
      //     return SecsItem.SecsIndexType.U2;
      // }
      // else if (parentVid == 67890) // VID 67890 is <L[2] <A string1> <U4 number1>>
      // {
      //     if (itemIndex == 0) return SecsItem.SecsIndexType.A;
      //     if (itemIndex == 1) return SecsItem.SecsIndexType.U4;
      // }

      // Fallback or error if type cannot be determined
      logger_SystemError.Warn($"[DetermineListItemSecsType] Undetermined SECS type for Parent VID: {parentVid}, Item Index: {itemIndex}, Item Value: '{TruncateValueForLog(listItem)}', Item Type: {listItem?.GetType().FullName}. Implement specific logic.");

      // A very generic attempt (likely insufficient for robust SECS implementation)
      if (listItem is string) return SecsItem.SecsIndexType.A;
      if (listItem is byte || listItem is sbyte) return SecsItem.SecsIndexType.U1; // Or I1 if signed
      if (listItem is ushort || listItem is short) return SecsItem.SecsIndexType.U2; // Or I2
      if (listItem is uint || listItem is int) return SecsItem.SecsIndexType.U4; // Or I4
      if (listItem is ulong || listItem is long) return SecsItem.SecsIndexType.U8; // Or I8
      if (listItem is float) return SecsItem.SecsIndexType.F4;
      if (listItem is double) return SecsItem.SecsIndexType.F8;
      if (listItem is bool) return SecsItem.SecsIndexType.Boolean;
      if (listItem is byte[]) return SecsItem.SecsIndexType.B; // Or U1 if it's a single byte conceptually

      return default(SecsItem.SecsIndexType); // Indicates type could not be determined
  }

  private string TruncateValueForLog(object value, int maxLength = 100)
  {
      if (value == null) return "<null>";

      string sValue;
      if (value is byte[] bytes)
      {
          // For byte arrays, show a snippet if too long
          if (bytes.Length > (maxLength / 2 - 5)) // Approximation: 2 chars per byte + "0x" + "..."
          {
              sValue = "0x" + BitConverter.ToString(bytes, 0, Math.Min(bytes.Length, maxLength / 2 - 10)).Replace("-", "") + "...";
          }
          else
          {
              sValue = "0x" + BitConverter.ToString(bytes).Replace("-", "");
          }
      }
      else
      {
          sValue = value.ToString();
      }

      if (sValue.Length > maxLength)
      {
          return sValue.Substring(0, maxLength - 3) + "...";
      }
      return sValue;
  }